package event

import (
	"context"
	"sync"

	"github.com/gorilla-go/container"
	"github.com/gorilla-go/pig/constant"
)

// EventHandler 事件处理函数类型
type EventHandler func(e *Event)

// EventManager 事件管理器
type EventManager struct {
	mu        sync.RWMutex
	listeners map[EventType][]EventHandler
	events    map[EventType]Event
}

// 创建新的EventManager
func NewEventManager() *EventManager {
	return &EventManager{
		mu:        sync.RWMutex{},
		listeners: make(map[EventType][]EventHandler),
		events:    make(map[EventType]Event),
	}
}

// GetEventManager 获取事件管理器实例
func GetEventManager(ctx context.Context) *EventManager {
	return container.GetMustLazySingletonByAlias[*EventManager](
		ctx.Value(constant.Container).(*container.Container),
		constant.EventManager,
	)
}

// AddEventListener 添加事件监听器
func (em *EventManager) AddEventListener(eventType EventType, handler EventHandler) {
	em.mu.Lock()
	defer em.mu.Unlock()

	em.listeners[eventType] = append(em.listeners[eventType], handler)
}

// RemoveEventListener 移除事件监听器
func (em *EventManager) RemoveEventListener(eventType EventType, handler EventHandler) {
	em.mu.Lock()
	defer em.mu.Unlock()

	handlers := em.listeners[eventType]
	for i, h := range handlers {
		if &h == &handler {
			em.listeners[eventType] = append(handlers[:i], handlers[i+1:]...)
		}
	}
}

// Dispatch 触发事件
func (em *EventManager) DispatchEvent(e Event, data map[string]any) {
	em.mu.RLock()
	if _, ok := em.listeners[e.Type]; !ok {
		em.mu.RUnlock()
		return
	}
	em.mu.RUnlock()

	// 处理当前级别的事件
	for _, handler := range em.listeners[e.Type] {
		handler(&e)

		// 停止冒泡
		if e.StopFlag {
			continue
		}

		// 处理父级事件
		if len(e.Parents) > 0 {
			for _, parent := range e.Parents {
				if parentEvent, ok := em.events[parent]; ok {
					pe := parentEvent
					pe.Data = e.Data
					em.DispatchEvent(pe.Type, pe.Data)
				}
			}
		}
	}
}
